#include "server.h"    // 包含服务端接口声明
#include "dlist.h"     // 包含双向链表接口（管理客户端）
#include "log.h"       // 包含日志接口（输出调试/错误信息）
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h> // 网络套接字相关头文件
#include <netinet/in.h> // 网络地址结构体（sockaddr_in）
#include <arpa/inet.h>  // 字节序转换（htons/inet_ntoa）
#include <errno.h>      // 错误码处理（errno）

/*
 * @brief 服务端初始化函数
 * @param port 服务端监听端口（如 8080）
 * @return 成功返回 Server 实例指针，失败返回 NULL
*/
    // 2. 初始化服务端地址结构体（清零，避免随机值干扰）


Server* server_init(int port) {
Server* server = (Server*)malloc(sizeof(Server));
    if (server == NULL) {
        log_error("server_init: 内存分配失败（errno: %d, msg: %s）",
                  errno, strerror(errno));
        return NULL;
    }

    // 2. 初始化服务器地址结构体（关键修正：正确使用memset）
    memset(&server->server_addr, 0, sizeof(server->server_addr)); // 清零结构体
    server->server_addr.sin_family = AF_INET;         // IPv4 协议
    server->server_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有网卡（0.0.0.0）
    server->server_addr.sin_port = htons(port);       // 端口转换为网络字节序（大端）

    // 3. 创建 TCP 套接字（SOCK_STREAM 表示流式套接字，即 TCP）
    server->server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server->server_fd < 0) {
        log_error("server_init: 创建套接字失败（port: %d, errno: %d, msg: %s）",
                  port, errno, strerror(errno));
        free(server); // 释放已分配的内存，避免泄漏
        return NULL;
    }

    // 4. 设置套接字选项：允许端口复用（避免服务重启时 "address already in use" 错误）
    int opt = 1;
    if (setsockopt(server->server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        log_warn("server_init: 设置端口复用败失");
        // 此处不终止，仅警告（端口复用非必需，但建议开启）
    }

    // 5. 绑定套接字到指定端口和地址
    if (bind(server->server_fd, 
             (struct sockaddr*)&server->server_addr, 
             sizeof(server->server_addr)) < 0) {
        log_error("server_init: 绑定端口失败（port: %d, errno: %d, msg: %s）",
                  port, errno, strerror(errno));
        close(server->server_fd); // 关闭已创建的套接字
        free(server);             // 释放内存
        return NULL;
    }

    // 6. 开始监听套接字（最大等待连接队列长度为 10）
    if (listen(server->server_fd, 10) < 0) {
        log_error("server_init: 监听端口失败（port: %d, errno: %d, msg: %s）",
                  port, errno, strerror(errno));
        close(server->server_fd);
        free(server);
        return NULL;
    }

    // 7. 初始化客户端管理链表（用于存储在线客户端连接）
    struct Server* server_init(int port){
    if (server->client_list == NULL) {
        log_error("server_init: 客户端链表初始化失败");
        close(server->server_fd);
        free(server);
        return NULL;
    }

    // 8. 初始化成功，输出日志
    log_info("server_init: 服务端初始化完成（监听端口: %d, 套接字FD: %d",
             port, server->server_fd);

    return server;
}
void server_start(struct Server* server) {
    if (server == NULL || server->server_fd < 0) {
        log_error("server_start: 服务器未正确初始化");
        return;
    }

    while (1) {
        struct sockaddr_in client_addr;  // 客户端地址结构体
        socklen_t client_addr_len = sizeof(client_addr); // 地址长度

        // 接受客户端连接（阻塞，直到有新连接或错误）
        int client_fd = accept(server->server_fd,
                               (struct sockaddr*)&client_addr,
                               &client_addr_len);
        if (client_fd < 0) {
            log_error("server_start: 接受连接失败（errno: %d, msg: %s）",
                      errno, strerror(errno));
            continue; // 继续等待下一个连接，不终止服务
        }

        // 连接成功，输出客户端信息（IP + 端口）
        log_info("server_start: 新客户端连接（IP: %s, 端口: %d, 客户端FD: %d）",
                 inet_ntoa(client_addr.sin_addr), // 转换IP为字符串
                 ntohs(client_addr.sin_port),     // 转换端口为本地字节序
                 client_fd);

        // 将客户端 FD 加入链表（后续可用于广播、断开连接等操作）
        dlist_append(server->client_list, (void*)(intptr_t)client_fd);
    }
}

    // 1. 关闭监听套接字
    if (server->server_fd >= 0) {
        close(server->server_fd);
        log_info("server_destroy: 监听套接字已关闭（FD: %d）", server->server_fd);
    }

    // 2. 关闭所有在线客户端连接（遍历链表，关闭每个客户端 FD）
    if (server->client_list != NULL) {
        dlist_traverse(server->client_list, (void(*)(void*))close);
        log_info("server_destroy: 所有客户端连接已关闭（共 %d 个客户端）",
                 dlist_get_size(server->client_list));

        // 3. 销毁客户端链表（释放链表节点内存）
        dlist_destroy(server->client_list);
        log_info("server_destroy: 客户端链表已销毁");
    }

    // 4. 释放服务端结构体内存
    free(server);
    log_info("server_destroy: 服务端资源已完全释放");
}
